<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.name">
      <dt>{{item.name}}</dt>
      <dd>
        <template  v-for="val in item.values" :key="val.name">
            <img  @click="clickSpecs(item,val)" :class="{selected:val.selected,disabled:val.disabled}" :src="val.picture" :title="val.name" v-if="val.picture">
            <span @click="clickSpecs(item,val)" :class="{selected:val.selected,disabled:val.disabled}" v-else>{{val.name }}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
import getPowerSet from '@/vender/power-set'
// 返回对象key值的分隔符
const spliter = '★'
// 处理幂集算法数据的函数
const gatPathMap = (skus) => {
//   定义空的路径字典
  const pathMap = {}
  skus.forEach(sku => {
    //   获取有效库存的数据
    if (sku.inventory) {
    //   console.log(sku)
      // 💥💥💥 getPowerSet 幂集算法，接收参数为数组，会自动展开为所有可能的数组
      const powerSet = getPowerSet(sku.specs.map(item => item.valueName))
      //   console.log(powerSet, 111)
      //   对所有的数组进行处理，变为路径字典的key
      powerSet.forEach(set => {
        //   路径字典的key值
        const key = set.join(spliter)
        // 💥💥💥如果没有key，生成key，并将第一次id添加到值中（值为数组）
        if (!pathMap[key]) {
          pathMap[key] = [sku.id]
        } else {
          // 如果已经有key值了，那么就直接追加id即可
          pathMap[key].push(sku.id)
        }
      })
    }
  })
  return pathMap
}

// 获取中规格的数组
const getSelectedArr = (specs) => {
//   console.log(specs)
// 定义空数组存放选中的规格
  const selectedArr = []
  //   遍历规格的数据，
  specs.forEach(spec => {
    //   💥💥💥将里面selected 属性为true的对象筛选出来
    const selectedVal = spec.values.find(val => val.selected)
    // 如果有这个对象就提前name属性出来，没有就设为undefined，并将值push进去存放规格的数组中
    selectedArr.push(selectedVal ? selectedVal.name : undefined)
  })
  //   返回选中规格的数组
  return selectedArr
}

// 💥💥💥禁止状态，预判用户的下一步操作，把规格的数据和路径字典的数据传进来
const updateDisabledStatus = (specs, pathMap) => {
//   console.log(specs, pathMap, 1111)
// 遍历规格中的每一项
  specs.forEach((spec, index) => {
    //   获取选择规格的数组
    const selectedArr = getSelectedArr(specs)
    // 🧨🧨遍历规格中的values数组，用来匹配里面的name属性
    spec.values.forEach((val) => {
      // 如果name属性在选中规格的数组中，说明已经选中的按钮不用判断
      if (val.name === selectedArr[index]) return
      // 💥💥💥如果还没有在选中规格的数组中，就将值赋值过去，用来作为预判用户下一步的操作
      selectedArr[index] = val.name
      //   将选中规格数组中不是undefined的值筛选出来，并拼接成路径字典的key
      const key = selectedArr.filter(v => v).join(spliter)
      // 🧨🧨 如果key 对应的值存在，disabled就为false，否则就为true，实现禁用功能
      val.disabled = !pathMap[key]
    })
  })
}

// 如果用户传入了skuId,需要初始化选中状态的规格
const initSelectedStatus = (goods, skuId) => {
//   console.log(goods, skuId)
// 🧨🧨🧨查找skus库中对应Id的那一项出来
  const obj = goods.skus.find(sku => sku.id === skuId)
  //   console.log(obj, 11)
  //   如果有对象才进行初始化选中状态
  if (obj) {
    //   对里面的规格数组进行遍历
    goods.specs.forEach((spec, index) => {
      // 🧨🧨🧨取出选中状态对应对象中的规格名字
      const value = obj.specs[index].valueName
      // console.log(spec, value, 222)
      //   💥💥💥将规格数组中的values 进行遍历，将里面name属性等于选中对象中的规格名字的项添加selected属性为true
      spec.values.forEach(val => {
        val.selected = val.name === value
      })
    })
  }
}
export default {
  name: 'GoodsSku',
  props: {
    goods: {
      type: Object,
      default: () => ({})
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  setup (props, { emit }) {
    //   引入获取路径字典的函数
    const pathMap = gatPathMap(props.goods.skus)
    // console.log(pathMap)
    // 预判用户下一步操作，并给规格添加禁止状态
    updateDisabledStatus(props.goods.specs, pathMap)
    // 如果用户已经有规格skuId时的规格数据复现函数
    initSelectedStatus(props.goods, props.skuId)
    //   规格点击事件
    const clickSpecs = (theItem, theVal) => {
      if (theVal.disabled) return
      //   console.log(theItem, theVal)
      // 自定义属性selected用来判定是否选中状态
      if (!theVal.selected) {
        // 没有选中先清空所有的状态，再将自己的改为true
        theItem.values.forEach(item => (item.selected = false))
        theVal.selected = true

        // 💥💥💥选择完了后要判定选中数组是否完整
        const res = getSelectedArr(props.goods.specs)
        // console.log(res)
        // 如果数组中包含undefined，说明规格未完整
        if (res.includes(undefined)) {
          // 没有选完规格时需要传空对象给父组件
          emit('change', {})
          console.log(1, '没完整')
        } else {
          // 否则，完整
          console.log(2, '完整')
          //   将数组组成路径字典的key值
          const key = res.join(spliter)
          //   因为路径字典的值为数组，所以对里面的数据进行解构
          const [skuId] = pathMap[key]
          //   console.log(skuId)
          //   💥💥💥在skus数组中找出skuId对应的项
          const obj = props.goods.skus.find(item => item.id === skuId)
          //   console.log(obj)
          //  对数据进行改造成父组件需要的数据
          const data = {
            skuId: obj.id,
            inventory: obj.inventory,
            oldPrice: obj.oldPrice,
            price: obj.price,
            attrsText: obj.specs.map(({ name, valueName }) => `${name}:${valueName}`).join(' ')
          }
          //   console.log(data)
          //   传出去给父组件
          emit('change', data)
        }
      } else {
        //   如果选中了就直接取消
        theVal.selected = false

        // 取消时需要传空对象给父组件
        emit('change', {})
      }
      //   每次点击完成都要对用户下一步操作的数据进行预判，并展示禁止状态
      updateDisabledStatus(props.goods.specs, pathMap)
    }
    return { clickSpecs }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
